/*
 * Copyright 2010 Biz-e (info@biz-e.nl)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.biz_e.acl.client.ui.context;

import nl.biz_e.acl.client.data.ContextController;
import nl.biz_e.acl.client.data.ContextController.ContextListHolder;
import nl.biz_e.acl.client.data.validation.ValidationException;
import nl.biz_e.acl.shared.model.Context;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * Complete form panel to edit Context objects
 * 
 * @author Joost A. Bloemsma
 * 
 */
public class ContextForm extends Composite implements ContextListHolder {
	
	private static ContextFormUiBinder uiBinder = GWT
			.create(ContextFormUiBinder.class);
	private Context ctx;
	private ContextController controller = new ContextController();
	
	@UiField
	TextBox idFld;
	@UiField
	TextBox nameFld;
	@UiField
	TextArea descrFld;
	@UiField
	ParentBox parentBox;
	@UiField
	Button cancelBtn;
	@UiField
	Button saveBtn;
	
	interface ContextFormUiBinder extends UiBinder<Widget, ContextForm> {
		/* Intentionally left blank */
	}
	
	/**
	 * Constructs a new ContextForm instance
	 */
	public ContextForm() {
		initWidget(uiBinder.createAndBindUi(this));
		controller.fillContexts(this);
	}
	
	@UiHandler("cancelBtn")
	void onClickCancel(ClickEvent e) {
		this.reset();
	}
	
	@UiHandler("saveBtn")
	void onClickSave(ClickEvent e) {
		this.save();
	}
	
	@UiHandler("parentBox")
	void onChange(ChangeEvent e) {
		if (!controller.isValidParentId(parentBox.getSelectedContextId())) {
			throw new ValidationException("A Context cannot be it's own parent");
			
		}
	}
	
	/**
	 * {@inheritDoc}
	 */
	public void setExistingContexts(Iterable<Context> ctxs) {
		parentBox.setContexts(ctxs);
	}
	
	/**
	 * Sets the Context instance to be shown (and editted)
	 * 
	 * @param ctx
	 */
	public void setContext(Context ctx) {
		this.ctx = ctx;
		reset();
		this.controller.setCtx(ctx);
	}
	
	private void save() {
		Context c = new Context();
		fillContext(c);
		controller.setCtx(c);
		controller.save();
		controller.fillContexts(this);
	}
	
	private void reset() {
		if (ctx == null) {
			clear();
			return;
		}
		
		idFld.setText(ctx.getContextId());
		nameFld.setText(ctx.getName());
		descrFld.setText(ctx.getDescription());
		
	}
	
	/**
	 * Fills the current Context with the new values.
	 * 
	 * @return The current (or new) Context instance
	 */
	public Context getContext() {
		fillContext(this.ctx);
		return this.ctx;
	}
	
	/**
	 * Fills a new instance of {@link Context} with the current values.
	 * Can be used to do some validations before the values are actually set to
	 * the real object.
	 * 
	 * @return new {@link Context}
	 */
	public Context getValues() {
		Context tmpCtx = new Context();
		fillContext(tmpCtx);
		return tmpCtx;
	}
	
	private void fillContext(Context c) {
		if (c == null) {
			c = new Context();
		}
		c.setContextId(idFld.getText());
		c.setName(nameFld.getText());
		c.setDescription(descrFld.getText());
		this.ctx = c;
	}
	
	private void clear() {
		this.ctx = null;
		idFld.setText("");
		nameFld.setText("");
		descrFld.setText("");
		parentBox.setSelectedIndex(0);
	}
}
